﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Windows.Media;
using Styx;
using Styx.Helpers;
using Styx.Common;
using Styx.CommonBot.POI;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.Pathing;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Styx.TreeSharp;
using Action = Styx.TreeSharp.Action;

namespace Lockery
{
    public partial class Classname : CombatRoutine
    {
        public override sealed string Name { get { return "Destruction Warlock CC by Pasterke"; } }

        public override WoWClass Class { get { return WoWClass.Warlock; } }

        private static LocalPlayer Me { get { return StyxWoW.Me; } }

        private void slog(string format, params object[] args) //use for slogging
        {
            Logging.Write(Colors.Yellow, format, args);
        }

        public override bool WantButton { get { return true; } }

        public override void OnButtonPress()
        {
            Lockery.LockeryForm ConfigForm = new LockeryForm();
            ConfigForm.ShowDialog();
        }

        public override void Initialize()
        {
            Updater.CheckForUpdate();
        }

        private static Stopwatch pullTimer = new Stopwatch();

        private static Stopwatch fightTimer = new Stopwatch();

        private static Stopwatch dotTimer = new Stopwatch();

        private static Stopwatch MoveBackTimer = new Stopwatch();

        private static Stopwatch petPresenceTimer = new Stopwatch();

        private static Stopwatch dismountTimer = new Stopwatch();

        private static ulong lastGuid = 0;

        private float naarTarget = 35f;

        public string Dotting = "notdone";

        private WoWUnit myPrimaryTarget { get; set; }

        public bool RemoveDeadTargets = true;

        private double MyTargetDistance
        {
            get
            {
                return Me.CurrentTarget != null ? Me.CurrentTarget.Distance : uint.MaxValue - 5;
            }
        }

        public override void Pulse()
        {
            try
            {
                if (Me.Combat && Me.CurrentTarget.IsFriendly)
                {
                    Me.ClearTarget();
                    LogMsg("Friendly Target removed because I'm in Combat (" + Me.CurrentTarget.Name + ")", 1);
                    return;
                }
                if (Me.Combat && RemoveDeadTargets && Me.CurrentTarget.IsDead)
                {
                    Me.ClearTarget();
                    LogMsg("Dead Target removed (" + Me.CurrentTarget.Name + ")", 1);
                    return;
                }
                if (!Me.CurrentTarget.Lootable
                    && Me.CurrentTarget.IsDead
                    && RemoveDeadTargets
                    && Me.CurrentTarget.Distance >= 3.5f)
                {
                    Me.ClearTarget();
                    LogMsg("Looted Target removed (" + Me.CurrentTarget.Name + ")", 1);
                    return;
                }

            }
            catch { }
        }
        #region CC_Begin


        public override bool NeedRest
        {
            get
            {
                if (UseSpells
                    && !Me.IsSwimming)
                {
                    if (Me.Pet != null
                        && Me.GotAlivePet
                        && Me.Pet.HealthPercent <= LockerySettings.myPrefs.HealthTunnelOutCombat
                        && UseSkill(HealthFunnel))
                    {
                        return true;
                    }
                    if (Me.ManaPercent <= LockerySettings.myPrefs.DrinkMana)
                    {
                        return true;
                    }
                    if (Me.HealthPercent <= LockerySettings.myPrefs.EatDrink)
                    {
                        return true;
                    }
                }
                return false;
            }
        }

        public override void Rest()
        {
            if (Me.Pet != null
                 && Me.GotAlivePet
                 && Me.Pet.HealthPercent <= LockerySettings.myPrefs.HealthTunnelOutCombat
                 && UseSkill(HealthFunnel))
            {
                CastSpell(HealthFunnel, 2);
            }
            if (Me.ManaPercent <= LockerySettings.myPrefs.DrinkMana
                && !Me.IsSwimming)
            {
                Styx.CommonBot.Rest.Feed();
            }
            if (Me.HealthPercent <= LockerySettings.myPrefs.EatDrink
                && !Me.IsSwimming)
            {
                Styx.CommonBot.Rest.Feed();
            }

        }

        #endregion

        #region Pull

        public override void Pull()
        {
            EnsureTarget();

            if (Me.GotTarget &&
                Me.CurrentTarget.IsPet)
            {
                Blacklist.Add(Me.CurrentTarget, TimeSpan.FromDays(1));
                Me.ClearTarget();
            }

            if (Me.GotTarget && Me.CurrentTarget.Mounted)
            {
                Blacklist.Add(Me.CurrentTarget, TimeSpan.FromMinutes(1));
                Me.ClearTarget();
            }
            if (gotTarget
                && Me.CurrentTarget.IsDead)
            {
                Me.ClearTarget();
            }
            if (Me.CurrentTarget.Guid != lastGuid)
            {
                fightTimer.Reset();
                lastGuid = Me.CurrentTarget.Guid;
                slog("Killing " + Me.CurrentTarget.Name + " at distance " + System.Math.Round(MyTargetDistance).ToString() + ".");
                pullTimer.Reset();
                pullTimer.Start();

            }
            else
            {
                if (pullTimer.ElapsedMilliseconds > 30 * 1000)
                {
                    slog("Cannot pull " + Me.CurrentTarget.Name + " now.  Blacklist for 3 minutes.");
                    Blacklist.Add(Me.CurrentTarget.Guid, System.TimeSpan.FromMinutes(3));
                }
            }
            if (Me.CurrentTarget.Distance > naarTarget)
            {
                MoveInRange(naarTarget);
            }
            else
            {
                if (Me.IsMoving)
                {
                    WoWMovement.MoveStop();
                }

                Me.CurrentTarget.Face();

                if (gotTarget
                    && LockerySettings.myPrefs.CallPet == "Voidwalker")
                {
                    Lua.DoString("PetAttack()");
                }
                if (UseSkill(CurseOfTheElements))
                {
                    CastSpell(CurseOfTheElements, 6);
                }
                else if (UseSkill(CurseOfEnfeeblement)
                    && !SpellManager.HasSpell(CurseOfTheElements))
                {
                    CastSpell(CurseOfEnfeeblement, 6);
                }
                else if (Me.Level >= 12
                    && UseSkill(Immolate)
                    && !SpellManager.HasSpell(CurseOfTheElements)
                    && LastSpell != Immolate)
                {
                    CastSpell(Immolate, 6);
                }
                else if (Me.Level < 12
                    && UseSkill(Corruption)
                    && !SpellManager.HasSpell(Immolate)
                    && LastSpell != Corruption)
                {
                    CastSpell(Corruption, 6);
                }
                else if (Me.Level < 10
                    && UseSkill(ShadowBolt))
                {
                    CastSpell(ShadowBolt, 6);
                }
                if (!Me.Pet.IsAutoAttacking)
                {
                    Lua.DoString("PetAttack()");
                }
            }

        }


        #endregion

        #region Pull Buffs

        public override bool NeedPullBuffs { get { return false; } }

        public override void PullBuff() { }

        #endregion

        #region Pre Combat Buffs

        public override bool NeedPreCombatBuffs
        {
            get
            {
                if (UseSpells)
                {
                    if (Me.IsSwimming
                    && UseSkill(UnendingBreath)
                    && !Me.HasAura(UnendingBreath))
                    {
                        CastBuff(UnendingBreath, 2);
                    }
                    if (SpellManager.HasSpell(DarkIntent)
                        && !buffExists(DarkIntent, Me))
                    {
                        CastBuff("Dark Intent", 2);
                    }
                    if (LockerySettings.myPrefs.AlchFlask == 1
                        && !FlaskBuff()
                        && !Me.HasAura("Enhanced Inttelect"))
                    {
                        AlchemistFlask();
                    }

                    CreateNewHealthStone();

                    if (UseSkill(Soulstone)
                        && !buffExists(SoulStone, Me)
                        && !spellOnCooldown(SoulStone)
                        && LockerySettings.myPrefs.SoulstoneOnMe)
                    {
                        CastBuff(Soulstone, 2);
                    }
                    if (Me.Pet == null
                        && !Me.Mounted
                        && !Me.IsFlying
                        && !Me.OnTaxi
                        && !Me.IsOnTransport
                        && !Me.IsGhost)
                    {
                        dismountTimer.Restart();
                    }
                    if (dismountTimer.Elapsed.Seconds > 3
                        && Me.Pet == null)
                    {
                        CallPet();
                    }
                }
                return false;
            }
        }

        public override void PreCombatBuff() { }

        #endregion

        #region Combat Buffs

        public override bool NeedCombatBuffs { get { return false; } }

        public override void CombatBuff()
        {

        }

        #endregion

        #region Heal

        public override bool NeedHeal { get { return false; } }


        public override void Heal() { }

        #endregion

        #region Falling

        public void HandleFalling() { }

        #endregion

        #region Combat

        public override void Combat()
        {
            if (!RestNeeded())
            {
                if (UseSkill(DarkBargain)
                        && GetSpellCooldown(DarkBargain).TotalSeconds == 0
                        && Me.HealthPercent <= 25)
                {
                    CastSpell(DarkBargain, 2);
                }
                if (UseSkill(EmberTap)
                    && Me.HealthPercent <= LockerySettings.myPrefs.EmberTap
                    && Me.GetCurrentPower(WoWPowerType.BurningEmbers) >= 10)
                {
                    CastBuff(EmberTap, 2);
                }
                if (UseSkill(DrainLife)
                && Me.HealthPercent <= LockerySettings.myPrefs.DrainLife)
                {
                    CastSpell(DrainLife, 3);
                }
                if (Me.HealthPercent <= LockerySettings.myPrefs.HealthPotion)
                {
                    Drinken();
                }
                if (Me.HealthPercent <= LockerySettings.myPrefs.healthstone)
                {
                    HealthStone();
                }
                if (Me.HealthPercent <= LockerySettings.myPrefs.LifeSpirit)
                {
                    LifeSpirit();
                }
                if (Me.HealthPercent <= LockerySettings.myPrefs.EngiBeltHealth)
                {
                    UseEngibelt();
                }
                if (Me.HealthPercent <= LockerySettings.myPrefs.HealthPotion)
                {
                    Drinken();
                }
                if (SpellManager.HasSpell("Gift of the Naruu")
                    && Me.HealthPercent <= LockerySettings.myPrefs.GiftOfNaruu)
                {
                    CastBuff("Gift of the Naaru", 2);
                }
                if (NeedClearTarget)
                {
                    Me.ClearTarget();
                }
                if (SpellManager.HasSpell(DarkIntent)
                    && !buffExists(DarkIntent, Me))
                {
                    CastBuff("Dark Intent", 2);
                }
                if (Me.IsSwimming
                    && UseSkill(UnendingBreath)
                    && !Me.HasAura(UnendingBreath))
                {
                    CastBuff(UnendingBreath, 2);
                }
                if ((Me.Pet == null
                    || Me.Pet.IsDead)
                    && !buffExists(GrimoireOfSacrifice, Me))
                {
                    CallPet();
                    dismountTimer.Reset();
                }  
                if (UseSkill(Soulstone)
                        && !Me.HasAura(Soulstone)
                        && LockerySettings.myPrefs.SoulstoneOnMe)
                {
                    CastBuff(Soulstone, 2);
                }
                if (LockerySettings.myPrefs.AlchFlask == 1
                    && !FlaskBuff()
                    && !Me.HasAura("Enhanced Inttelect"))
                {
                    AlchemistFlask();
                }

                UseTrinket1(); UseTrinket2(); UseEngiGloves();

                if (Me.CurrentTarget != null
                    && LockerySettings.myPrefs.PotionBuff == 1
                    && Me.GroupInfo.IsInRaid)
                {
                    myPotion();
                }
                if (Me.CurrentTarget != null
                    && LockerySettings.myPrefs.BuffFlask == 1
                    && Me.GroupInfo.IsInRaid)
                {
                    myFlask();
                }

                if (!Me.GotTarget
                    && Me.Pet != null
                    && (Me.Pet.Combat
                    || Me.Pet.Aggro))
                {
                    if (Me.Pet.CurrentTarget != null)
                    {
                        Me.ClearTarget();
                        Me.Pet.CurrentTarget.Target();
                    }
                    Facing();
                    MoveInRange(35);
                    LogMsg("Taking pet's target", 1);
                }
                if (Me.CurrentTarget != null
                    && !LockerySettings.myPrefs.DisableTargetting)
                {
                    EnsureTarget();
                }
                if (Me.CurrentTarget != null
                    && !LockerySettings.myPrefs.DisableFacing)
                {
                    Facing();
                }
                if (Me.CurrentTarget != null
                    && !LockerySettings.myPrefs.DisableMovement)
                {
                    MoveInRange(35);
                }
                if (Me.CurrentTarget != null
                    && IsBoss)
                {
                    BossRotation();
                }
                if (Me.CurrentTarget != null
                    && NeedAoeRotation)
                {
                    AoeRotation();
                }
                if (Me.CurrentTarget != null
                    && !NeedAoeRotation)
                {
                    MainRotation();
                }
            }

        }

        #endregion


        #region Spells

        private void AutoAttack()
        {
            if (!Me.IsAutoAttacking)
            {
                Lua.DoString("StartAttack()");
            }

        }
        #endregion Spells

        #region rotation
        public void MainRotation()
        {
            if (!RestNeeded())
            {

                if (UseSkill(CurseOfTheElements)
                    && !Me.CurrentTarget.HasAura(CurseOfTheElements)
                    && LastSpell != CurseOfTheElements)
                {
                    CastSpell(CurseOfTheElements, 4);
                    return;
                }
                if (UseSkill(CurseOfEnfeeblement)
                    && !SpellManager.HasSpell(CurseOfTheElements)
                    && !Me.CurrentTarget.HasAura(CurseOfEnfeeblement)
                    && LastSpell != CurseOfEnfeeblement)
                {
                    CastSpell(CurseOfEnfeeblement, 4);
                    return;
                }

                UseTrinket1();
                UseTrinket2();
                UseEngiGloves();

                if (Me.Pet != null
                    && Me.GotAlivePet
                    && Me.Pet.HealthPercent <= LockerySettings.myPrefs.HealthTunnel
                    && UseSkill(HealthFunnel)
                    && Me.HealthPercent > LockerySettings.myPrefs.HealthTunnel)
                {
                    CastSpell(HealthFunnel, 2);
                    return;
                }
                if (UseSkill(Fear)
                    && Me.CurrentTarget.IsPlayer
                    && !Me.CurrentTarget.Fleeing)
                {
                    CastSpell(Fear, 3);
                    return;
                }
                if (UseSkill(MortalCoil)
                    && Me.CurrentTarget.IsPlayer
                    && Me.HealthPercent <= 75)
                {
                    CastSpell(MortalCoil, 3);
                }
                if (UseSkill(TwilightWard)
                    && Me.CurrentTarget.IsPlayer
                    && EnemySpec())
                {
                    CastSpell(TwilightWard, 3);
                    return;
                }
                if (UseSkill(SummonInfernal)
                && !LockerySettings.myPrefs.SummonInfernal
                && GetSpellCooldown(SummonInfernal).TotalSeconds == 0
                && addCount > 1)
                {
                    Lua.DoString("CastSpellByName('Summon Infernal');");
                    {
                        SpellManager.ClickRemoteLocation(StyxWoW.Me.CurrentTarget.Location);
                        LogMsg(">> Summon Infernal <<", 3);
                    }
                    return;

                }
                if (UseSkill(SummonDoomguard)
                && !LockerySettings.myPrefs.SummonDoomguard
                && GetSpellCooldown(SummonDoomguard).TotalSeconds == 0)
                {
                    CastSpell(SummonDoomguard, 3);
                    return;
                }
                if (gotTarget
                    && SpellManager.HasSpell(DarkSoul)
                    && LockerySettings.myPrefs.DarkSoul == 1
                    && !spellOnCooldown(DarkSoul)
                    && LastSpell != "Dark Soul")
                {
                    if (SpellManager.CanCast(DarkSoul))
                    {
                        SpellManager.CanCast(DarkSoul);
                        LogMsg("Dark Soul", 3);
                        LastSpell = "Dark Soul";
                    }
                }

                /*if (gotTarget
                    && addCount > 1
                    && Me.GetCurrentPower(WoWPowerType.BurningEmbers) >= 10)
                {
                    EnsureHavoc();
                }*/

                if (UseSkill(ChaosBolt)
                    && Me.CurrentTarget.HealthPercent >= 20
                    && Me.GetCurrentPower(WoWPowerType.BurningEmbers) >= 10)
                {
                    CastSpell(ChaosBolt, 3);
                    return;
                }
                if (UseSkill(ShadowBurn)
                    && Me.CurrentTarget.HealthPercent < 20
                    && Me.GetCurrentPower(WoWPowerType.BurningEmbers) >= 10)
                {
                    CastSpell(ShadowBurn, 3);
                    return;
                }
                if (Me.Level < 12
                    && UseSkill(Corruption)
                    && !SpellManager.HasSpell(Immolate)
                    && (!Me.CurrentTarget.HasAura(Corruption)
                    || MyAuraTimeLeft(Corruption, Me.CurrentTarget) < 3000)
                    && Me.CurrentTarget.HealthPercent > LockerySettings.myPrefs.NoCorruption
                    && LastSpell != Corruption)
                {
                    CastSpell(Corruption, 3);
                    return;
                }
                if (Me.Level >= 12
                    && UseSkill(Immolate)
                    && (!Me.CurrentTarget.HasAura(Immolate)
                    || MyAuraTimeLeft(Immolate, Me.CurrentTarget) < 2000)
                    && Me.CurrentTarget.HealthPercent > LockerySettings.myPrefs.NoCorruption
                    && !IsBoss
                    && LastSpell != Immolate)
                {
                    CastSpell(Immolate, 4);
                    return;
                }
                if (UseSkill(Conflagrate)
                    && GetSpellCooldown(Conflagrate).TotalSeconds == 0
                    && LastSpell != Conflagrate)
                {
                    CastSpell(Conflagrate, 3);
                    return;
                }
                if (UseSkill(Incinerate))
                {
                    CastSpell(Incinerate, 3);
                    return;
                }
                if (Me.Level < 10
                    && UseSkill(ShadowBolt))
                {
                    CastSpell(ShadowBolt, 3);
                    return;
                }
            }
        }
        #endregion Mainrotation

        #region AoeRotation

        public void AoeRotation()
        {
            if (UseSkill(CurseOfTheElements)
                    && !Me.CurrentTarget.HasAura(CurseOfTheElements)
                    && LastSpell != CurseOfTheElements)
            {
                CastSpell(CurseOfTheElements, 4);
                return;
            }
            if (!SpellManager.HasSpell(FireAndBrimbstone))
            {
                if (UseSkill(RainOfFire))
                {
                    Firerain();
                    return;
                }
            }

            /*if (gotTarget
                && Me.GetCurrentPower(WoWPowerType.BurningEmbers) >= 10)
            {
                EnsureHavoc();
            }*/

            if (UseSkill(FireAndBrimbstone)
                && Me.GetCurrentPower(WoWPowerType.BurningEmbers) == 10)
            {
                CastSpell(FireAndBrimbstone, 5);

                if (!Me.CurrentTarget.HasAura(Immolate))
                {
                    CastSpell(Immolate, 5);
                }
                return;
            }
            if (Me.CurrentTarget.HasAura(Immolate)
                && UseSkill(RainOfFire))
            {
                Lua.DoString("CastSpellByName('Rain of Fire');");
                {
                    SpellManager.ClickRemoteLocation(StyxWoW.Me.CurrentTarget.Location);
                    LogMsg(">> Rain of Fire <<", 5);
                }
            }
            if (UseSkill(Conflagrate)
                && Me.GetCurrentPower(WoWPowerType.BurningEmbers) < 10)
            {
                CastSpell(Conflagrate, 5);
                return;
            }
            if (UseSkill(Incinerate)
                && Me.GetCurrentPower(WoWPowerType.BurningEmbers) < 10)
            {
                CastSpell(Incinerate, 5);
                return;
            }
        }

        #endregion AoeRotation

        #region bossrotation

        public void BossRotation()
        {
            if (UseSkill(CurseOfTheElements)
                    && !Me.CurrentTarget.HasAura(CurseOfTheElements)
                    && LastSpell != CurseOfTheElements)
            {
                CastSpell(CurseOfTheElements, 4);
                return;
            }
            if (UseSkill(CurseOfEnfeeblement)
                && !SpellManager.HasSpell(CurseOfTheElements)
                && !Me.CurrentTarget.HasAura(CurseOfEnfeeblement)
                && LastSpell != CurseOfEnfeeblement)
            {
                CastSpell(CurseOfEnfeeblement, 4);
                return;
            }
            if (gotTarget
                    && SpellManager.HasSpell(DarkSoul)
                    && (LockerySettings.myPrefs.DarkSoul == 2
                    || LockerySettings.myPrefs.DarkSoul == 1)
                    && !spellOnCooldown(DarkSoul)
                    && LastSpell != "Dark Soul")
            {
                if (SpellManager.CanCast(DarkSoul))
                {
                    SpellManager.CanCast(DarkSoul);
                    LogMsg("Dark Soul", 3);
                    LastSpell = "Dark Soul";
                }
            }
            if (Me.Level >= 12
                  && UseSkill(Immolate)
                  && !Me.CurrentTarget.HasAura(Immolate)
                  && LastSpell != Immolate)
            {
                CastSpell(Immolate, 4);
                return;
            }

            UseTrinket1();
            UseTrinket2();
            UseEngiGloves();

            if (UseSkill(FireAndBrimbstone)
                && addCount > 1
                && GetSpellCooldown(FireAndBrimbstone).TotalSeconds == 0
                && Me.GetCurrentPower(WoWPowerType.BurningEmbers) == 10
                && Me.CurrentTarget.HasAura(Immolate))
            {
                CastSpell(FireAndBrimbstone, 5);
                return;
            }
            if (UseSkill(SummonInfernal)
                && LockerySettings.myPrefs.SummonInfernal
                && GetSpellCooldown(SummonInfernal).TotalSeconds == 0
                && addCount > 3)
            {
                Lua.DoString("CastSpellByName('Summon Infernal');");
                {
                    SpellManager.ClickRemoteLocation(StyxWoW.Me.CurrentTarget.Location);
                    LogMsg(">> Summon Infernal <<", 3);
                }
                return;

            }
            if (UseSkill(SummonDoomguard)
                && LockerySettings.myPrefs.SummonDoomguard
                && GetSpellCooldown(SummonDoomguard).TotalSeconds == 0)
            {
                CastSpell(SummonDoomguard, 3);
                return;
            }

            /*if (gotTarget
                && addCount > 1
                && Me.GetCurrentPower(WoWPowerType.BurningEmbers) >= 10)
            {
                EnsureHavoc();
            }*/

            if (UseSkill(ChaosBolt)
                && Me.GetCurrentPower(WoWPowerType.BurningEmbers) >= 10
                && Me.CurrentTarget.HealthPercent >= 20)
            {
                CastSpell(ChaosBolt, 3);
                return;
            }
            if (UseSkill(ShadowBurn)
                && Me.GetCurrentPower(WoWPowerType.BurningEmbers) >= 10
                && Me.CurrentTarget.HealthPercent < 20)
            {
                CastSpell(ShadowBurn, 3);
                return;
            }
            if (UseSkill(Conflagrate)
                 && GetSpellCooldown(Conflagrate).TotalSeconds == 0
                 && LastSpell != Conflagrate)
            {
                CastSpell(Conflagrate, 3);
                return;
            }
            if (UseSkill(Incinerate))
            {
                CastSpell(Incinerate, 3);
                return;
            }
        }
        #endregion bossrotation

        #region Pet
        public void CallPet()
        {
            if (LockerySettings.myPrefs.AutoCallPet)
            {
                string myPet = "Summon " + LockerySettings.myPrefs.CallPet;
                
                if ((Me.Pet == null
                    || Me.Pet.IsDead)
                    && !buffExists(GrimoireOfSacrifice, Me)
                    && !Me.Mounted
                    && !Me.IsFlying
                    && LastSpell != "CallPet"
                    && !Me.IsChanneling)
                {
                    SpellManager.Cast(myPet);
                    Logging.Write(Colors.PaleGreen, myPet);
                    LastSpell = "CallPet";
                }
            }
            return;
        }
        #endregion pet

    }
}

